#include "animate_loop.h"

LinerAnimateAttribute::LinerAnimateAttribute( const std::string &id, const std::string &name, int begin, int end, float beginTime, LinerAnimateStyle style )
    : AnimateAttribute( id, name, AnimateTypeLinear )
    , m_nBegin( begin )
    , m_nEnd( end )
    , m_fBeginTime( beginTime )
    , m_fTime( 0 )
    , m_style( style )
{
}

void LinerAnimateAttribute::Frame( float fElapse, float fTotal )
{
    if( m_fTime >= m_fBeginTime && !IsEnd() )
    {
        if( m_fTime == fTotal )
        {
            SetEnd();
        }

        int nValue = 0;
        switch( m_style )
        {
        case LinerAnimateStyleLiner:
            nValue = tween::Linear<int>::calculate(
                m_fTime - m_fBeginTime,
                m_nBegin,
                m_nEnd - m_nBegin,
                fTotal - m_fBeginTime );
            break;

        default:
            break;
        }

        char szValue[ 16 ] = { 0 };
        _itoa_s( nValue, szValue, 10 );

        AttributeHandler * pHandler = new AttributeHandler( m_strId, m_strName, szValue );
        if( pHandler )
        {
            ThreadManager::Instance().MessageQueue()->PostQueueTask( m_pDelegate, TASK_ANIMATE_SET_ATTRIBUTE, pHandler );
        }
    }

    m_fTime += fElapse;
    if( m_fTime > fTotal )
    {
        m_fTime = fTotal;
    }
}

Animate::Animate( const std::string &id )
    : m_strId( id )
{
}

Animate::~Animate()
{
}

void Animate::SetDelegate( ITaskDelegate *delegate )
{
    for( _attributes::iterator iter = m_attributes.begin();
         iter != m_attributes.end() && *iter;
         iter++ )
    {
        (*iter)->SetDelegate( delegate );
    }
}

void Animate::RegisterAnimateObserver( IAnimateObserver * observer )
{
    if( observer )
        m_observers.push_back( observer );
}

Animate& Animate::PutLinerAttribute
                (
                  const std::string &name,
                  int begin,
                  int end,
                  LinerAnimateStyle style,
                  float beginTime
                 )
{
    if( name.empty() )
        return *this;

    LinerAnimateAttribute * attribute = new LinerAnimateAttribute( m_strId, name, begin, end, beginTime, style );
    if( attribute )
        m_attributes.push_back( attribute );

    return *this;
}

void Animate::Begin()
{
    NotifyObservers( AnimateBegin );
}

void Animate::Frame( float fElapse, float fTotal )
{
    for( _attributes::iterator iter = m_attributes.begin();
         iter != m_attributes.end() && *iter;
         iter++ )
    {
        (*iter)->Frame( fElapse, fTotal );
    }
}

void Animate::End()
{
    NotifyObservers( AnimateEnd );
}

void Animate::NotifyObservers( AnimateState state )
{
    for( _observers::iterator iter = m_observers.begin();
         iter != m_observers.end();
         ++iter )
    {
        if( !*iter )
            continue;

        (*iter)->OnAnimateStateChanged( m_strId, state );
    }
}

AnimateHandler::AnimateHandler( float fElapse, float fTotal )
    : m_fElapse( fElapse )
    , m_fTotal( fTotal )
    , m_fTime( 0.0 )
{

}

AnimateHandler::~AnimateHandler()
{

}

void AnimateHandler::SetDelegate( ITaskDelegate *delegate )
{

}

void AnimateHandler::Handle( HANDLE hEvent )
{

}

void AnimateHandler::Drop()
{

}

SingleAnimateHandler::SingleAnimateHandler( float fElapse, float fTotal, Animate *animate )
    : AnimateHandler( fElapse, fTotal )
    , m_Animate( animate )
{
}

SingleAnimateHandler::~SingleAnimateHandler()
{
}

void SingleAnimateHandler::SetDelegate( ITaskDelegate *delegate )
{
    if( m_Animate )
        m_Animate->SetDelegate( delegate );
}

void SingleAnimateHandler::Handle( HANDLE hEvent )
{
    if( m_Animate && ::WaitForSingleObject( hEvent, 0 ) == WAIT_TIMEOUT )
    {
        m_Animate->Begin();
    }

    while( m_Animate )
    {
        m_Animate->Frame( m_fElapse, m_fTotal );
        if( m_fTime == m_fTotal )
        {
            break;
        }

        m_fTime += m_fElapse;
        if( m_fTime >= m_fTotal )
        {
            m_fTime = m_fTotal;
        }

        if( ::WaitForSingleObject( hEvent, (DWORD)m_fElapse ) == WAIT_TIMEOUT )
            continue;
        else
            break;
    }

    if( m_Animate && ::WaitForSingleObject( hEvent, 0 ) == WAIT_TIMEOUT )
    {
        m_Animate->End();
    }
}

void SingleAnimateHandler::Drop()
{
    if( m_Animate )
        delete m_Animate;

    delete this;
}

ComplexAnimateHandler::ComplexAnimateHandler( float fElapse, float fTotal )
    : AnimateHandler( fElapse, fTotal )
{
}

ComplexAnimateHandler::~ComplexAnimateHandler()
{
}

void ComplexAnimateHandler::SetDelegate( ITaskDelegate *delegate )
{
    for( _animates::iterator iter = m_animates.begin();
         iter != m_animates.end() && *iter;
         ++iter )
    {
        (*iter)->SetDelegate( delegate );
    }
}

void ComplexAnimateHandler::PutAnimate( Animate * animate )
{
    if( animate )
        m_animates.push_back( animate );
}

void ComplexAnimateHandler::Handle( HANDLE hEvent )
{
    if( ::WaitForSingleObject( hEvent, 0 ) == WAIT_TIMEOUT )
    {
        for( _animates::iterator iter = m_animates.begin();
             iter != m_animates.end() && *iter;
             ++iter )
        {
            (*iter)->Begin();
        }
    }

    while( m_animates.size() > 0 )
    {
        for( _animates::iterator iter = m_animates.begin();
             iter != m_animates.end() && *iter;
             ++iter )
        {
            (*iter)->Frame( m_fElapse, m_fTotal );
        }

        if( m_fTime == m_fTotal )
        {
            break;
        }

        m_fTime += m_fElapse;
        if( m_fTime >= m_fTotal )
        {
            m_fTime = m_fTotal;
        }

        if( ::WaitForSingleObject( hEvent, (DWORD)m_fElapse ) == WAIT_TIMEOUT )
            continue;
        else
            break;
    }

    if( ::WaitForSingleObject( hEvent, 0 ) == WAIT_TIMEOUT )
    {
        for( _animates::iterator iter = m_animates.begin();
             iter != m_animates.end() && *iter;
             ++iter )
            (*iter)->End();
    }
}

void ComplexAnimateHandler::Drop()
{
    for( _animates::iterator iter = m_animates.begin();
         iter != m_animates.end();
         ++iter )
    {
        if( *iter )
            delete (*iter);
    }

    m_animates.clear();
}

MessageLoopAM::MessageLoopAM()
{
}

MessageLoopAM::~MessageLoopAM()
{
}